#include "03_ThreadPool.h"
#include <iostream>
#include <mutex>

using std::cout;
using std::endl;
using std::thread;
//using std::lock_guard;
//using std::unique_lock;

#define LOG_WHERE() \
    std::clog << "[DEBUG] " << __FILE__ << ":" << __LINE__ << " (" << __FUNCTION__ << ")\n"

// 构造函数（线程数, 队列容量）
ThreadPool::ThreadPool(size_t threadnum, size_t capacity)
    :_threadnum(threadnum)
    ,_threads()
    ,_capacity(capacity)
    ,_taskQue(_capacity)
    ,_isExit(false)
{}

// 析构函数
ThreadPool::~ThreadPool()
{}

// 启动线程池
void ThreadPool::start()
{
    // 创建线程
    for(size_t i = 0; i < _threadnum; ++i){
        _threads.emplace_back(&ThreadPool::doTask, this);
    }
    LOG_WHERE();
}

// 停止线程池
void ThreadPool::stop()
{
//    {
//        lock_guard<mutex> lock(_thmutex);
//        _isExit = true;
//    }   // 出作用域后自动解锁

    while(!_taskQue.empty())
    {
        //让主线程放弃对CPU的控制权，防止CPU空转
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    LOG_WHERE();

    _isExit = true;

    _taskQue.wakeup();
    LOG_WHERE();

    for(auto& th : _threads)
    {
        if(th.joinable()) th.join();    
        LOG_WHERE();
    }
    LOG_WHERE();
}

// 添加任务
void ThreadPool::addTask(function<void()>&& ptask)
{
    _taskQue.TaskPush(std::move(ptask));
    LOG_WHERE();
}

// 获取任务（内部使用）
function<void()> ThreadPool::getTask()
{
    return _taskQue.TaskPop();
}

// 任务执行逻辑（内部使用）
void ThreadPool::doTask()
{
    LOG_WHERE();
    while(!_isExit)
    {
        function<void()> task = getTask(); // 获取基类指针
        if(task){
            task();
        }      
    }

    // Task::Process();     // 错误的调用方式
    //    Task* task = getTask(); // 获取基类指针
    //    if(task){
    //        task->Process();    // 指向派生类对象
    //    }
}
